home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 014 / libtools.arc / MEMTEST.AQM / MEMTEST.ASM
Encoding:
Assembly Source File  |  1984-04-08  |  11.6 KB  |  391 lines

  1.     page    60,132
  2.     title    MEMTEST - Software Technique's Memory Test
  3. ;
  4. ; MEMTEST - A fast parity check for all memory on option cards
  5. ;
  6. ;  Copyright, 1983, Software Technique, Inc.  Permission is
  7. ;    granted to copy and distribute, provided this copyright
  8. ;    notice remains on all copies made.
  9. ;
  10. ;  This program tests Planar (lower 64K) or add-on memory by performing
  11. ;  initialization and fast successive reads, reporting any errors it
  12. ;  finds.  If the program is loaded in low memory (LINK memtest;), it
  13. ;  will test the add-on memory.  If it is loaded into high memory (LINK
  14. ;  memtest/h;), it will test the lower 64K bytes, with the exclusion of
  15. ;  the first 0600H bytes of RAM.  This program is fast; it does
  16. ;  not perform the (probably) more exhaustive tests of IBM's Advanced
  17. ;  diagnostics, but it is materially faster.  It is especially useful
  18. ;  for finding the intermittent kinds of errors that seem to crop up
  19. ;  only after several hours.  The principle is simple:    We write all of
  20. ;  memory with a consistent pattern, and then we sweep through and read
  21. ;  it again and again.    We capture all Non-maskable Interrupts so you
  22. ;  won't see the "PARITY CHECK 2" or "PARITY CHECK 1" messages.
  23. ;
  24. ;  The display shows the current status of testing, and up to 22 found
  25. ;  errors.  After 22 errors, the program waits for manual intervention
  26. ;  so you can let it run overnight and the errors will be displayed on
  27. ;  the screen when you return.    Use Shift-PrtSc to print out the error
  28. ;  messages.
  29. ;
  30. ;  An "odometer" is maintained on the screen that displays the number
  31. ;  of read cycles since the last time memory was "primed" with the
  32. ;  known pattern.  The "odometer" is named the "Cycle count."  When the
  33. ;  count is blank, the program is initializing memory.    The counter is
  34. ;  incremented at the start of each read sweep.
  35. ;
  36. ;  Errors are discriminated into three types:
  37. ;        Parity Error  (that is, NMI struck & bits are bad)
  38. ;      Spurious NMI Error  (that is, NMI struck, but no bad bits)
  39. ;          Mismatch Error  (that is, no parity error, but the bits
  40. ;                    weren't what we expected)
  41. ;  The error message reports in the following format:
  42. ;        SSSS:OOOO=BB(XX/YY)   where
  43. ;            SSSS = Segment (always N000 or N800)
  44. ;            OOOO = Offset (always < 8000)
  45. ;              BB = One's in places where bits are bad
  46. ;              XX = Pattern read from memory in error
  47. ;              YY = Second pattern read from memory after
  48. ;                error detected
  49. ;  We take care to make sure that we reread reportedly faulty bit
  50. ;  places several times; this assures us some coverage of the "floating
  51. ;  output" problem for missing chips or memory devices that won't
  52. ;  enable their outputs.  We check for pattern mismatch because parity
  53. ;  checks only detect odd numbers of bits in error (two or four bits in
  54. ;  error in a byte won't be caught by parity).
  55. ;
  56. ;  After an error is reported, testing resumes from the next 32K byte
  57. ;  bank.  After the end of memory has been reached, it will be re-
  58. ;  initialized and the "Cycle" count will be reset to zero.  If two
  59. ;  or more errors are found during a sweep, the second and successive
  60. ;  error lines will not have the "Cycle" counter displayed.
  61. ;
  62. ;  Please report problems to Carol Anne Ogdin at 703/549-0646
  63. ;
  64. ;
  65. PORTB    equ    61H
  66. PORTC    equ    62H
  67. KBDIN    equ    60H
  68. VIDEO    macro
  69.     mov    ah,0EH        ;Write as if to TTY
  70.     int    10H
  71.     endm
  72. DISPLAY macro    TXT
  73.     mov    si,offset TXT
  74.     call    TTYOUT
  75.     endm
  76. ;
  77. TEST    segment
  78.     assume    cs:TEST,es:TEST
  79.     db    'Copr. 1983 Software Technique, Inc. V1.0'
  80. CYCLES    dw    0    ;Number of passes made
  81. MINI    db    0    ;Number of lines displayed so far
  82. MAX    equ    22    ;Maximum number of displayed lines permitted
  83. FLAG    db    0    ;Non-zero if NMI
  84. SAVE    db    0    ;Faulty bits during write/read test
  85. FIRST    db    0    ;First-read faulty byte
  86. SECOND    db    0    ;Second-read faulty byte
  87. FOUND    db    0    ;Found-an-error this pass
  88. TABLE    db    '0123456789ABCDEF';Hex conversion
  89. MSG1A    db    '        Parity',0
  90. MSG1B    db    '  Spurious NMI',0
  91. MSG1C    db    '      Mismatch',0
  92. MSG7    db    ' Error at ',0
  93. MSG2    db    'Cycle:     ',0
  94. MSG2A    db    '           ',0
  95. MSG3    db    4 dup (08H),0    ;Backspace over prior cycle number
  96. MSG6    db    0DH,0AH,'Software Technique, Inc. '
  97. MSG6A    db    'Add-on RAM Test'
  98.     db    0DH,0AH,'Hit any key to stop, Alt-Ctrl-Del to end'
  99. MSG4    db    0DH,0AH,0    ;Carriage Return, Line Feed (new line)
  100. MSG5    db    'Hit any key to resume testing.',0
  101. MSG8    db    'Planar'
  102. ;
  103. ; Main entry point
  104. ;
  105. INIT:    mov    FOUND,-1    ;Mark memory as needing a refresh
  106.     mov    ax,cs        ;Figure out which bank we're in
  107.     mov    ds,ax        ;Make (ds)=(es)=(cs)
  108.     mov    es,ax
  109.     test    ah,0F0H
  110.     jz    RECYCLE
  111.     mov    cx,6        ;Change message form
  112.     mov    di,offset MSG6A
  113.     mov    si,offset MSG8
  114. rep    movsb
  115. RECYCLE:call    CLEAR
  116. ;
  117. ; Initialize for the next sweep
  118. ;
  119. REFRESH:cmp    FOUND,0     ;Any reason to refresh the memory?
  120.     je    PRESET
  121.     call    SETALL        ;Prime the memory (and clear FOUND)
  122. PRESET: mov    ax,cs        ; Make (ds)=(cs) again
  123.     mov    ds,ax
  124. ;
  125. ; This program shows the number of memory read cycles on the current
  126. ; Video Display line.  When an error occurs, it shows the segment,
  127. ; offset and the bit(s) in error (as 1's in a field of zeros).  The
  128. ; program displays successive errors on successive lines of the display
  129. ; and waits for operator specification before erasing the display.
  130. ;
  131. START:    mov    bh,0
  132.     cmp    FOUND,0     ;If any error found
  133.     jne    NEXT        ;  then end the pass
  134.     mov    ah,1        ;Check for keyboard action
  135.     int    16H
  136.     jnz    STOP        ;Stop reading
  137.     DISPLAY MSG3        ;Back up over prior cycle number display
  138.     inc    CYCLES        ;Increment cycle count
  139.     jz    NEXT        ;Start a new line after 64K tries!
  140.     mov    ax,CYCLES    ;Show cycles run in Hex
  141.     call    HEXOUT
  142. ;
  143.     call    GETSIZE     ;Find memory size to read (set cx)
  144. RESUME: call    READALL     ;Check for errors
  145.     mov    dx,ds        ;save DS
  146.     mov    ax,cs        ; and restore old DS
  147.     mov    ds,ax
  148.     jo    START        ;Finished this pass
  149. ; Error found.    dx:bx=address of error, SAVE=faulty bits
  150.     push    dx        ;Save segment for resumption later
  151.     push    cx        ;  and the remaining bank count
  152.     mov    cx,bx        ;Save the offset in bank
  153.     mov    bh,0        ;Set for Screen 0
  154.     cmp    FOUND,0     ;See if this is second message
  155.     jz    SKIP        ;No.  first time, skip this
  156.     DISPLAY MSG2A        ;Align error messages
  157. SKIP:    call    ERROR        ;Go show error message
  158.     pop    cx        ;Restore remaining bank count
  159.     dec    cx        ;  and account for this one done
  160.     pop    dx        ;Reclaim bank segment number
  161.     add    dx,800H     ;  and advance to next
  162.     mov    FOUND,0FFH    ;Mark the cycle as having an error
  163.     jmp    RESUME        ;Resume reading for errors
  164. ;
  165. STOP:    mov    MINI,1        ;Force screen-full halt
  166. NEXT:    DISPLAY MSG4        ;Start a new line on display
  167.     mov    CYCLES,0    ;Reset read-cycle count
  168.     dec    MINI        ;Screen full yet?
  169.     jz    FULL        ; Yes.
  170.     DISPLAY MSG2        ;Show next line's Cycle message
  171.     jmp    REFRESH
  172. FULL:    DISPLAY MSG5        ;Ask for permission to go on
  173. FLUSH:    mov    ah,1        ;Flush out any waiting characters
  174.     int    16H
  175.     jz    WAIT
  176.     mov    ah,0        ;Get the waiting character
  177.     int    16H
  178.     jmp    FLUSH
  179. WAIT:    mov    ah,1        ;Wait for a keystroke
  180.     int    16H
  181.     jz    WAIT
  182.     mov    ah,0
  183.     int    16H
  184.     jmp    RECYCLE
  185. ;
  186. ;  Issue the error message and supporting information
  187. ;    at entry, (dx)=segment address, (cx)=offset, (bh)=0
  188. ;
  189. ERROR:    mov    si,offset MSG1C
  190.     cmp    FLAG,0
  191.     jz    ISSUE        ;No NMI.  Must've been mismatch
  192.     mov    si,offset MSG1B
  193.     cmp    SAVE,0
  194.     jz    ISSUE        ;No bits in error; Spurious NMI?
  195.     mov    si,offset MSG1A ;Must've been Parity error
  196. ISSUE:    call    TTYOUT
  197.     DISPLAY MSG7
  198.     mov    ax,dx        ;Show segment address
  199.     call    HEXOUT
  200.     mov    al,':'
  201.     VIDEO
  202.     mov    ax,cx        ;Reclaim offset
  203.     call    HEXOUT
  204.     mov    al,'='
  205.     VIDEO
  206.     mov    al,SAVE     ;Show error bit locations
  207.     call    BYTOUT
  208.     mov    al,'('
  209.     VIDEO
  210.     mov    al,FIRST    ;Show first byte read
  211.     call    BYTOUT
  212.     mov    al,'/'
  213.     VIDEO
  214.     mov    al,SECOND    ;  and then second
  215.     call    BYTOUT
  216.     mov    al,')'
  217.     VIDEO
  218.     ret
  219. ;
  220. HEXOUT: push    ax        ;Save low-order digit
  221.     mov    al,ah        ;Convert high digit first
  222.     call    BYTOUT        ;Issue one byte
  223.     pop    ax        ;Reclaim second byte
  224. BYTOUT: push    ax        ;Save digit
  225.     shr    al,1        ;Put high-order digit in low-order bits
  226.     shr    al,1
  227.     shr    al,1
  228.     shr    al,1
  229.     call    DIGOUT        ;Issue first digit
  230.     pop    ax        ;Get second digit back
  231. DIGOUT: and    al,0FH        ;isolate four bits
  232.     mov    bx,offset TABLE ;Setup to translate hex
  233.     xlat
  234.     mov    bh,0        ;Restore for video
  235.     VIDEO
  236.     ret
  237. ;
  238. ; Prime a 32K byte bank
  239. ;    ds: Base address of the bank
  240. ;
  241. PRIME:    mov    ds,dx        ;Set for this 32K page
  242. PRIME1: mov    byte ptr [bx],bl;Store count in next location
  243.     inc    bx
  244.     jno    PRIME1        ;Continue until 8000H
  245. SETXIT: ret
  246. ;
  247. ; Prime all of available memory
  248. ;
  249. SETALL: call    GETSIZE     ;How much memory to set?
  250.     mov    FOUND,0     ;Reset error-in-memory flag
  251. SETNEXT:jcxz    SETXIT
  252.     mov    ds,dx
  253.     call    PRIME        ;Prime next bank
  254.     add    dx,800H     ;Advance segment by 32K
  255.     mov    bx,0
  256.     dec    cx
  257.     jmp    SETNEXT
  258. ;
  259. ; Read all of a 32K bank, looking for an error
  260. ;
  261. READ:    mov    ds,dx
  262. READ1:    mov    al,[bx]     ;This reads a byte; NMI if parity error
  263.     test    FLAG,0FFH    ;  If there was an error,
  264.     jnz    READERR     ;     this will jump 'cause FLAG<>0
  265.     cmp    al,bl        ;This catches even # of bit errors
  266.     jnz    READERR
  267.     inc    bx
  268.     jno    READ1        ;Do until bx=8000H
  269.     ret
  270. READERR:mov    FIRST,al    ;Save the byte, as read
  271.     mov    al,[bx]     ;and try reading it again
  272.     mov    SECOND,al
  273.     mov    al,0        ;Assume no bits in error
  274.     mov    bh,10        ;Try these tests because of floats
  275. NEXTRY: mov    byte ptr [bx],0
  276.     or    al,[bx]     ;Get some perhaps bad bits
  277.     mov    byte ptr [bx],0FFH ;Try the complement
  278.     mov    ah,[bx]
  279.     xor    ah,0FFH     ;Complement the result
  280.     or    al,ah        ;Put bad bits together
  281.     dec    bh
  282.     jnz    NEXTRY
  283.     mov    SAVE,al
  284.     ret            ;Note:    OF is clear (by 'or')
  285. ;
  286. ; Read all add-on memory, using READ for each 32K byte bank
  287. ;  At entry, (cx) = # of 32K banks yet to scan
  288. ;         (dx) = segment address of next bank to scan
  289. ;
  290. READALL:mov    FLAG,0    ;Clear markers
  291.     mov    SAVE,0
  292.     call    GETSIZE     ;Set up (dx), (bx) and (cx)
  293. ;Save the existing NMI interrupt routine vector and set our own
  294.     xor    ax,ax
  295.     mov    es,ax
  296.     mov    ax,es:8
  297.     push    ax        ;Save IP
  298.     mov    ax,es:10
  299.     push    ax        ;Save CS
  300.     mov    word ptr es:8,offset NMISVC
  301.     mov    word ptr es:10,cs ;Use this segment
  302. RDNEXT: jcxz    RDEXIT
  303.     call    READ        ;And cycle through it
  304.     jno    RDERR        ;Oops.    Found an error, so quit
  305.     mov    bx,0
  306.     add    dx,800H
  307.     dec    cx
  308.     jmp    RDNEXT
  309. RDEXIT: mov    al,07FH
  310.     rol    al,1        ;Set OF to mark no error
  311. RDERR:    pop    ax        ;Get back saves CS:IP for 10:8
  312.     mov    word ptr es:10,ax
  313.     pop    ax
  314.     mov    word ptr es:8, ax
  315.     ret
  316. ; Find the size of the memory we're about to read or write
  317. GETSIZE:mov    ax,cs        ;Am I in Low or High memory?
  318.     test    ah,0F0H     ;See if we're above first 64K
  319.     jz    HITEST        ;I'm in low memory, so test HIGH
  320.     mov    bx,600H     ;Skip first 600H bytes for BIOS
  321.     mov    dx,0
  322.     mov    cx,2        ;Only do two banks
  323.     ret
  324. HITEST: in    al,PORTC    ;Read DIP switches
  325.     and    al,0FH
  326.     cbw
  327.     mov    cx,ax        ;Leave count of 32K banks in (cx)
  328.     mov    dx,1000H    ;Assume we start just above Planar
  329.     mov    bx,0
  330.     ret
  331. ;
  332. ; Video display routines
  333. ;
  334. CLEAR:    mov    ax,cs        ;Make (ds)=(cs)
  335.     mov    ds,ax
  336.     mov    ax,0500H    ;Set for Screen Page 0
  337.     int    10H
  338.     mov    ah,0FH        ;Find out screen size
  339.     int    10H
  340.     mov    dl,ah        ;Put away biggest column
  341.     mov    dh,25
  342.     mov    cx,0
  343.     mov    ax,0600H
  344.     mov    bh,2        ;Set normal attribute
  345.     int    10H        ;Clear screen
  346.     mov    bh,0        ;Select Screen Page 0
  347.     mov    dx,0        ;Set cursor to upper left corner
  348.     mov    ah,2
  349.     int    10H
  350.     mov    CYCLES,0    ;Reset counters
  351.     mov    MINI,MAX
  352.     DISPLAY MSG6
  353.     mov    si,offset MSG2
  354. ;
  355. ; TTYOUT assumes that (bh)=0 to select screen #0
  356. TTYOUT: mov    al,[si]     ;Get next byte
  357.     inc    si
  358.     cmp    al,0        ;Finished?
  359.     je    TTYXIT        ;Yes.
  360.     VIDEO
  361.     jmp    TTYOUT
  362. TTYXIT: ret
  363. ;
  364. ; NMI Substitute Routine
  365. ;
  366. NMISVC    proc    near
  367.     push    ax
  368.     in    al,PORTC
  369.     test    al,40H        ;Parity 2?
  370.     jz    exit
  371.     mov    al,0
  372.     out    0A0H,al     ;disable NMI
  373.     in    al,PORTB
  374.     or    al,20H        ;Disable IO CK ENABLE so we can
  375.     out    PORTB,al    ;  strobe it to clear parity check
  376.     and    al,not 20h    ;Now, take it away again
  377.     out    PORTB,al
  378.     mov    al,80H
  379.     out    0A0H,al     ;Reenable NMI
  380.     mov    cs:FLAG,al    ;Set the FLAG to note the error
  381. EXIT:    pop    ax
  382.     iret
  383. NMISVC    endp
  384. ;
  385. TEST    ends
  386. ;
  387. SPAREA    segment stack
  388.     dw    256 dup (0)
  389. SPAREA    ends
  390.     end    INIT
  391.